from collections import defaultdict
import numpy
from scipy import sparse
from datetime import datetime
from sklearn.cross_validation import KFold
from sklearn.neighbors import NearestCentroid
from sklearn.dummy import DummyClassifier
from sklearn.metrics import classification_report
__author__ = 'pstalidis'


path = "/home/panagiotis/Projects/ICT4Growth/datasets/jester_1/"
name = "jester_dataset_1_1.csv"

choices = [0, -1, -1, -1, 1, 1]

t_users = [[int(round(float(w), 0)) for w in row] for row in [line.strip().split("\t") for line in open(path+name, 'rb')]]
v_users = numpy.array(numpy.choose(t_users, choices))  #
v_books = v_users.T
del t_users

t0 = datetime.now()
ratings = []
for user in xrange(0, v_users.shape[0]):
    for book in xrange(0, v_users.shape[1]):
        if v_users[user, book] != choices[0]:
            ratings.append({"user": user, "book": book, "score": v_users[user, book]})
ratings = numpy.array(ratings)

ten_fold = KFold(n=ratings.shape[0]-1, n_folds=10, shuffle=True)

results = {"predicted": [], "correct": []}
for train_indexes, test_indexes in ten_fold:
    per_user = defaultdict(lambda: {"train": [], "test": []})
    for d in ratings[train_indexes]:
        per_user[d["user"]]["train"].append((d["book"], d["score"]))
    for d in ratings[test_indexes]:
        per_user[d["user"]]["test"].append((d["book"], d["score"]))
    for user_id in per_user.keys():
        X_train = []
        y_train = []
        X_test = []
        y_test = []
        for (book_id, score) in per_user[user_id]["train"]:
            X_train.append(v_users[:, book_id])
            y_train.append(score)
        for (book_id, score) in per_user[user_id]["test"]:
            X_test.append(v_users[:, book_id])
            y_test.append(score)
        if (len(X_train) > 0) and (len(X_test) > 0):
            try:
                clf = NearestCentroid()
                clf.fit(X_train, y_train)
            except ValueError:
                clf = DummyClassifier(strategy="constant", constant=y_train[0])
                clf.fit(X_train, y_train)
            finally:
                results["predicted"] += clf.predict(numpy.vstack(X_test)).tolist()
                results["correct"] += y_test
        else:
            results["predicted"] += [0 for i in xrange(0, len(y_test))]
            results["correct"] += y_test

print "time taken", datetime.now() - t0
results['spredicted'] = [int(x) for x in results['predicted']]
results['scorrect'] = [int(x) for x in results['correct']]

results['predicted'] = numpy.choose(results['spredicted'], choices)
results['correct'] = numpy.choose(results['scorrect'], choices)

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
print "precision", precision_score(results['correct'], results['predicted'])
print "recall", recall_score(results['correct'], results['predicted'])
print "accuracy", accuracy_score(results['correct'], results['predicted'])
print "f-measure", f1_score(results['correct'], results['predicted'])

